﻿using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Media.Animation;

namespace Heyo.Controls.Animations
{
    public abstract class AnimationBorder : ClippingBorder
    {
        public static readonly DependencyProperty AnimationTriggerProperty = DependencyProperty.Register(
            "AnimationTrigger", typeof(bool), typeof(AnimationBorder), new PropertyMetadata(default(bool),
                AnimationTriggerChange));
        /// <summary>
        /// 动画完成时触发，参数为true表示反向动画
        /// </summary>
        public event EventHandler Completed;
        public event EventHandler InverseCompleted;
        public event EventHandler CurrentTime;
        public event EventHandler Started;
        public event EventHandler InverseStarted;
        private static void AnimationTriggerChange(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (e.NewValue == e.OldValue)
                return;

            if((bool)e.NewValue)
                ((AnimationBorder)d).BeginAnimation();
            else
                ((AnimationBorder)d).BeginInverseAnimation();

        }
        [Category("Animation")]
        public bool AnimationTrigger
        {
            get => (bool) GetValue(AnimationTriggerProperty);
            set => SetValue(AnimationTriggerProperty, value);
        }
        
        
        [Category("Animation")]
        public abstract Duration Duration { get; set; }

        [Category("Animation")]
        public abstract double SpeedRatio { get; set; }

        public static readonly DependencyProperty AnimFunctionProperty = DependencyProperty.Register(
            "AnimFunction", typeof(IEasingFunction), typeof(AnimationBorder), new PropertyMetadata(default(IEasingFunction)));


        [Category("Animation")]
        public IEasingFunction AnimFunction
        {
            get => (IEasingFunction)GetValue(AnimFunctionProperty);
            set => SetValue(AnimFunctionProperty, value);
        }

        protected abstract AnimationTimeline InitAnimation();
        protected abstract AnimationTimeline InitInverseAnimation();
        protected abstract DependencyProperty AnimationProperty { get; }
        protected abstract IAnimatable AnimationElement { get; }
        public void BeginAnimation()
        {
            AnimationTimeline anim = InitAnimation();
            anim.Completed += (s, e) => { Completed?.Invoke(s, e); };
            anim.CurrentTimeInvalidated += (s, e) => { CurrentTime?.Invoke(s, e); };
            AnimationElement.BeginAnimation(AnimationProperty, anim);
            Started?.Invoke(this,new EventArgs());
        }

        public void BeginInverseAnimation()
        {
            AnimationTimeline anim = InitInverseAnimation();
            anim.Completed += (s, e) => { InverseCompleted?.Invoke(s,e ); };
            anim.CurrentTimeInvalidated += (s, e) => { CurrentTime?.Invoke(s, e); };
            AnimationElement.BeginAnimation(AnimationProperty, anim);
            InverseStarted?.Invoke(this, new EventArgs());
        }
    }
}
